#include "yx020_app.h"
#include "yx020_port.h"
#include "main.h"

struct YX020APPManager {
	uint8_t modeSwitch : 1;
    uint8_t direction : 1;
	uint8_t reserved : 6;
	
	uint16_t brLen;
	uint16_t frameCnt;
	uint16_t chipNum;
	YX020DemoModeEnum demoMode;
	
	uint8_t *regs;
	YX020APPRGBTypedef *brArray;
};

static struct YX020APPManager *sManager = NULL;

void YX020APPInit(void)
{
	static struct YX020APPManager manager;
	static uint8_t regs[7];
#if defined(YX020APP_CHIP_VERSION_BACK)
	static YX020APPRGBTypedef brArray[YX020APP_CHIP_NUM];
#else
	static uint16_t brArray[YX020APP_GROUP_NUM * YX020APP_CHIP_N_EACH_G];
#endif
	
	uint16_t i;
	
	YX020APPRegInitTypedef *regInit = NULL;
	
	if (sManager == NULL) {
		manager.modeSwitch = 0;
		
		manager.frameCnt = 0;
	#if defined(YX020APP_CHIP_VERSION_BACK)
		manager.chipNum = YX020APP_CHIP_NUM;
	#else
		manager.chipNum = YX020APP_GROUP_NUM * YX020APP_CHIP_N_EACH_G;
	#endif
		manager.brLen = manager.chipNum * 3;
		manager.demoMode = YX020_DEMO_ALL_GREEN;
		
		manager.regs = regs;
		manager.brArray = brArray;
		
		sManager = &manager;
	}

    if (YX020PortCheckDir()) {
        manager.direction = 1;
    }
    else {
        manager.direction = 0;
    }
	
	for (i = 0; i < manager.chipNum; i++) {
		brArray[i].green = 0;
		brArray[i].red = 0;
		brArray[i].blue = 0;
	}
	
	regInit = (YX020APPRegInitTypedef *)pvPortMalloc(sizeof(YX020APPRegInitTypedef));
	regInit->gc = YX020APP_GC_5MA;
	regInit->bit8mode = YX020APP_8BIT_UNEN;
	regInit->isr = YX020APP_ISR_FAST;
	regInit->fault = YX020APP_FAULT_RM_UNEN;
	regInit->analog = YX020APP_ANALOG_EN;
	regInit->pulse = YX020APP_PULSE_BIG;
	regInit->watchdog = YX020APP_WATCH_DOG_EN;
	
	regInit->dcGreen = 0x3F;
	regInit->dcRed = 0x3F;
	regInit->dcBlue = 0x3F;
	
#if defined(YX020APP_CHIP_VERSION_ABB)
    regInit->chipNEachG = YX020APP_CHIP_N_EACH_G;
    regInit->bufNum = YX020APP_BUF_NUM;
#endif
    if (manager.direction) {
        regInit->ioDirection = YX020APP_IO_FORWAD;
        regInit->boardDirection = YX020APP_BOARD_FORWAD;
    }
    else {
        regInit->ioDirection = YX020APP_IO_REVERSE;
        regInit->boardDirection = YX020APP_BOARD_REVERSE;
    }
	
	regInit->vinDamp = YX020APP_VIN_DAMP_UNEN;
	regInit->updateMode = YX020APP_UPDATE_CONTI;
	regInit->lsdGear = YX020APP_LSD_GEAR_0;
	regInit->lastForward = YX020APP_LAST_FORW_UNEN;
	
	YX020APPGenREGVal(regs, regInit);
	vPortFree(regInit);
    YX020PortSetUartDir(manager.direction);
}

void YX020APPGenREGVal(uint8_t *regs, YX020APPRegInitTypedef *regInit)
{
	regs[0] = 0;
	regs[0] |= regInit->gc;
	regs[0] |= regInit->bit8mode;
	regs[0] |= regInit->isr;
	regs[0] |= regInit->fault;
	regs[0] |= regInit->analog;
	regs[0] |= regInit->pulse;
	regs[0] |= regInit->watchdog;
	
	regs[1] |= regInit->dcGreen;
	regs[2] |= regInit->dcRed;
	regs[3] |= regInit->dcBlue;
	
	regs[4] = 0;
#if defined(YX020APP_CHIP_VERSION_ABB)
	regs[4] |= regInit->chipNEachG;
	regs[4] |= regInit->bufNum;
#endif
	regs[4] |= regInit->ioDirection;
	regs[4] |= regInit->boardDirection;
	
	regs[6] = 0;
	regs[6] |= regInit->vinDamp;
	regs[6] |= regInit->updateMode;
	regs[6] |= regInit->lsdGear;
	regs[6] |= regInit->lastForward;
}

void YX020APPTask(void *parameter)
{
	uint16_t i;
    EventBits_t uxBits;
	
	YX020PortChipInit(sManager->regs[4], sManager->chipNum, 1, 0xCC, 1);
	YX020PortFrameHLBaud(sManager->regs, (uint16_t *)sManager->brArray, sManager->brLen, 0, 1);
	YX020PortTimerRun();
	
	for (i = 0; i < sManager->chipNum; i++) {
		sManager->brArray[i].green = 0x1000;
		sManager->brArray[i].red = 0x0000;
		sManager->brArray[i].blue = 0x0000;
	}
	
	while (1) {
		xEventGroupWaitBits(APPEventGroup, APP_EVENT_FRAME_FLUSE, pdTRUE, pdTRUE, 100);
		
		sManager->frameCnt++;
		YX020PortFrameHLBaud(sManager->regs, (uint16_t *)sManager->brArray, sManager->brLen, 0, 0);
		if (sManager->frameCnt == 60) {
			sManager->modeSwitch = 1;
			if (sManager->demoMode == YX020_DEMO_ALL_WHITE) {
				sManager->demoMode = YX020_DEMO_ALL_GREEN;
			}
			else {
				sManager->demoMode++;
			}
		}
		
		if (sManager->modeSwitch) {
			if (sManager->demoMode == YX020_DEMO_ALL_GREEN) {
				for (i = 0; i < sManager->chipNum; i++) {
					sManager->brArray[i].green = 0x1000;
					sManager->brArray[i].red = 0x0000;
					sManager->brArray[i].blue = 0x0000;
				}
			}
			else if (sManager->demoMode == YX020_DEMO_ALL_RED) {
				for (i = 0; i < sManager->chipNum; i++) {
					sManager->brArray[i].green = 0x0000;
					sManager->brArray[i].red = 0x1000;
					sManager->brArray[i].blue = 0x0000;
				}
			}
			else if (sManager->demoMode == YX020_DEMO_ALL_BLUE) {
				for (i = 0; i < sManager->chipNum; i++) {
					sManager->brArray[i].green = 0x0000;
					sManager->brArray[i].red = 0x0000;
					sManager->brArray[i].blue = 0x1000;
				}
			}
			else {
				for (i = 0; i < sManager->chipNum; i++) {
					sManager->brArray[i].green = 0x1000;
					sManager->brArray[i].red = 0x1000;
					sManager->brArray[i].blue = 0x1000;
				}
			}
		}
		
        uxBits = xEventGroupGetBits(APPEventGroup);
        if (APP_BIT_CHECK(uxBits, APP_EVENT_KEY0_HIGH) || APP_BIT_CHECK(uxBits, APP_EVENT_KEY0_LOW)) {
            xEventGroupClearBits(APPEventGroup, APP_EVENT_KEY0_HIGH | APP_EVENT_KEY0_LOW);
            YX020PortTimerStop();
            sManager->direction = YX020PortCheckDir();
            YX020PortSetUartDir(sManager->direction);
            if (sManager->direction) {
                sManager->regs[4] &= ~(YX020APP_IO_REVERSE);
                sManager->regs[4] |= YX020APP_IO_FORWAD;
                sManager->regs[4] &= ~(YX020APP_BOARD_REVERSE);
                sManager->regs[4] |= YX020APP_BOARD_FORWAD;
            }
            else {
                sManager->regs[4] |= YX020APP_IO_REVERSE;
                sManager->regs[4] |= YX020APP_BOARD_REVERSE;
            }
            YX020PortChipInit(sManager->regs[4], sManager->chipNum, 1, 0xCC, 1);
            vTaskDelay(10);
            YX020PortFrameHLBaud(sManager->regs, (uint16_t *)sManager->brArray, sManager->brLen, 0, 1);
            YX020PortTimerRun();
        }
	}
}
